package com.yitong.spiboot;


import com.yitong.spiboot.entity.Yplugin;
import com.yitong.spiboot.entity.YpluginEvent;
import com.yitong.spiboot.entity.YpluginProperties;
import com.yitong.spiboot.loader.JarLauncher;
import com.yitong.spiboot.loader.archive.Archive;
import com.yitong.spiboot.loader.archive.JarFileArchive;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringBootVersion;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;

import javax.servlet.ServletContext;
import java.io.File;
import java.net.URLClassLoader;
import java.util.Iterator;
import java.util.List;
import java.util.jar.Attributes;

@Slf4j
public class Spiboot implements BootService {

    String jarFilePath;
    Class lanhaiServiceApplication = null;
    URLClassLoader classLoader;
    YpluginServer ypluginServer;

    public Yplugin init(String yid, ApplicationContext applicationContext) {
        ypluginServer= applicationContext.getBean( YpluginServer.class );
        Yplugin yplugin = ypluginServer.getYplugin( yid );

        //获取当前启动的jar/war目录
        //获取的war包的路径为/WEB-INF/classes/,jar包路径为/BOOT-INF/classes,故需要做war包专属替换
        jarFilePath = yplugin.getFilePath();
        log.info( "tomcat中当前war/jar包根目录:" + jarFilePath );
        String version = SpringBootVersion.getVersion();
        //获取当前启动war包的源信息

        try {
            JarFileArchive archive = new JarFileArchive( new File( jarFilePath ) );
            Attributes attributes = archive.getManifest().getMainAttributes( );
            String value = attributes.getValue( "Spring-Boot-Version" );
            if(!checkVersion(version,value)){
                throw new RuntimeException("Springboot 版本不一致：母体版本是"+version+",插件版本是:"+value);
            }
            JarLauncher jarLauncher = new JarLauncher( archive );
            jarLauncher.launch( new String[]{} );
            Iterator <Archive> archives = jarLauncher.getClassPathArchivesIterator();
            classLoader = (URLClassLoader) jarLauncher.createClassLoader( archives );
            Thread.currentThread().setContextClassLoader( classLoader );
            String mainClass = jarLauncher.getMainClass();
            lanhaiServiceApplication = Class.forName( mainClass, false, Thread.currentThread().getContextClassLoader() );
            return yplugin;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException( "系统出错！！！" );
        }


    }


    public Boolean checkVersion (String str1,String str2){
        String[] appVersion1 = str1.split("\\.");
        String[] appVersion2 = str2.split("\\.");
        if(appVersion1[0].compareTo( appVersion2[0] )==0
                &&appVersion1[1].compareTo( appVersion2[1] )==0){
            return true;
        }

        return false;
    }

    public void onStartup(String pid, ServletContext servletContext, ApplicationContext applicationContext) {

        Yplugin init = init( pid, applicationContext );


        SpringApplicationBuilder o = new SpringApplicationBuilder( lanhaiServiceApplication );
        List <YpluginProperties> ypluginProperties = ypluginServer.getYpluginProperties( pid );
        MyServletWebServerApplicationContext annotationConfigServletWebServerApplicationContext = new MyServletWebServerApplicationContext( servletContext );
        annotationConfigServletWebServerApplicationContext.setServletContext( servletContext );
        annotationConfigServletWebServerApplicationContext.setApplicationContext(pid,applicationContext);
        SpringApplicationBuilder web = o
               // .parent( (ConfigurableApplicationContext)applicationContext )
                .web( WebApplicationType.NONE );
        this.configure( web );
//        String name = "app1";
//
        ConfigurableApplicationContext run1 = web
//                .registerShutdownHook( false )
                .contextFactory( (application) -> annotationConfigServletWebServerApplicationContext )
                .run( "--debug=false", "--spring.mvc.servlet.path=" + init.getPath(), "--spring.web.resources.static-locations=file:E:/GifCam" );

        applicationContext.publishEvent( new YpluginEvent(pid,servletContext,run1) );
    }


    /**
     * Configure the application. Normally all you would need to do is to add sources
     * (e.g. config classes) because other settings have sensible defaults. You might
     * choose (for instance) to add default command line arguments, or set an active
     * Spring profile.
     *
     * @param builder a builder for the application context
     * @return the application builder
     * @see SpringApplicationBuilder
     */
    public SpringApplicationBuilder configure(SpringApplicationBuilder builder) {


        log.info( "服务开始启动" );
        builder.main( lanhaiServiceApplication );
        return builder.sources( lanhaiServiceApplication );
    }

    public Class getMainClass() {
        return lanhaiServiceApplication;
    }


}
